/*
 * *
 *  * Created with IntelliJ RustRover.
 *  * Description:
 *  * Copyright Author: ZhenYi
 *  * DateTime: 2024/2/14 下午5:10
 *
 */

use std::ops::Add;
use rustis::resp::cmd;
use salvo::http::cookie::{Cookie, CookieBuilder};
use sea_orm::prelude::Date;
use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
use crate::config::pgsql::userlist;
use crate::utensil::cookie_queue::{CookieOps, CookieQueue};
use regex::Regex;
use rustis::commands::ConnectionCommands;

#[allow(unused)]
#[derive(Clone)]
pub struct LocalCookie{
    redis:rustis::client::Client,
    rx:tokio::sync::mpsc::Sender<CookieQueue>
}

#[derive(Deserialize,Serialize)]
pub struct Local {
    genre: i32,
    username: String,
    email: String,
    phone: String,
    name: String,
    sex: i32,
    birthday: Date,
    address: String,
    postalcode: String,
    jobtitle: String,
    companyname: String,
    companyaddress: String,
    department_faculty: Option<String>,
    research_direction: String,
    field_of_study: Option<String>,
}

impl From<userlist::Model> for Local {
    fn from(model: userlist::Model) -> Self {
        Local {
            genre: model.genre,
            username: model.username,
            email: model.email,
            phone: model.phone,
            name: model.name,
            sex: model.sex,
            birthday: model.birthday,
            address: model.address,
            postalcode: model.postalcode,
            jobtitle: model.jobtitle,
            companyname: model.companyname,
            companyaddress: model.companyaddress,
            department_faculty: model.department_faculty,
            research_direction: model.research_direction,
            field_of_study: model.field_of_study,
        }
    }

}
impl LocalCookie {
    pub fn new(redis:rustis::client::Client,rx:tokio::sync::mpsc::Sender<CookieQueue>) -> LocalCookie {
        LocalCookie {
            redis,
            rx,
        }
    }
    #[allow(unused)]
    pub fn future_60min() ->OffsetDateTime {
        let ts = std::time::SystemTime::now().add(std::time::Duration::from_secs(3600));
        let ts = time::OffsetDateTime::from(ts);
        ts
    }
    #[allow(unused)]
    pub fn future_will() ->OffsetDateTime {
        let ts = std::time::SystemTime::now().add(std::time::Duration::from_secs(1));
        let ts = time::OffsetDateTime::from(ts);
        ts
    }
    #[allow(unused)]
    pub async fn generate_save_cookie<'a>(&self,userinfo:userlist::Model) -> Cookie<'a> {
        let uuid = uuid::Uuid::new_v4();
        let cookie = CookieBuilder::new("Cookie",uuid.to_string().clone())
            .expires(Self::future_60min())
            .path("/")
            .http_only(true)
            .build();
        let model = serde_json::to_string(&userinfo).unwrap();
        self.rx.send(
            CookieQueue::new(
               CookieOps::AddCookie,
                (
                    uuid.to_string(),
                    model
                )
            )
        ).await.unwrap();
        cookie
    }
    #[allow(unused)]
    pub async fn get_local(&self, cookie:Cookie<'_>) -> String {
        self.update_expires(cookie.clone()).await;
        let res_body = self.redis.send(cmd("GET").arg(cookie.value().to_string()),None).await.unwrap();
        let re = Regex::new(r#"BulkString\("(.+)"\)"#).unwrap();
        let body = re.captures(&res_body.to_string()).unwrap().get(1).unwrap().as_str().to_string();
        let body = body.replace("\\","");
        let userinfo = serde_json::from_str::<userlist::Model>(&body).unwrap();
        let local = Local::from(userinfo);
        return serde_json::to_string(&local).unwrap();
    }
    #[allow(unused)]
    pub async fn del_cookie(&self,cookie:Cookie<'_>){
        self.rx.send(
            CookieQueue::new(
                CookieOps::DelCookie,
                (
                    cookie.value().to_string(),
                    "".to_string()
                )
            )
        ).await.unwrap();
    }
    #[allow(unused)]
    pub async fn update_expires<'a>(&self, cookie: Cookie<'a>) -> Cookie<'a> {
        let mut cookie = cookie.clone();
        cookie.set_expires(Self::future_60min());
        cookie.set_path("/");
        self.rx.send(
            CookieQueue::new(
                CookieOps::UpdateCookie,
                (
                    cookie.value().to_string(),
                    "".to_string()
                )
            )
        ).await.unwrap();
        return cookie
    }
    pub async fn is_admin<'a>(&self,cookie: Cookie<'a>) -> bool {
        self.redis.select(0).await.unwrap();
        let res_body = self.redis.send(cmd("GET").arg(cookie.value().to_string()),None).await.unwrap();
        let re = Regex::new(r#"BulkString\("(.+)"\)"#).unwrap();
        let body = re.captures(&res_body.to_string()).unwrap().get(1).unwrap().as_str().to_string();
        let body = body.replace("\\","");
        let userinfo = serde_json::from_str::<userlist::Model>(&body).unwrap();
        userinfo.genre == 1
    }
    pub async fn is_author(&self,cookie: Cookie<'_>) -> bool {
        self.redis.select(0).await.unwrap();
        let res_body = self.redis.send(cmd("GET").arg(cookie.value().to_string()),None).await.unwrap();
        let re = Regex::new(r#"BulkString\("(.+)"\)"#).unwrap();
        let body = re.captures(&res_body.to_string()).unwrap().get(1).unwrap().as_str().to_string();
        let body = body.replace("\\","");
        let userinfo = serde_json::from_str::<userlist::Model>(&body).unwrap();
        userinfo.genre == 2
    }
    pub async fn is_expert(&self,cookie: Cookie<'_>) -> bool {
        self.redis.select(0).await.unwrap();
        let res_body = self.redis.send(cmd("GET").arg(cookie.value().to_string()),None).await.unwrap();
        let re = Regex::new(r#"BulkString\("(.+)"\)"#).unwrap();
        let body = re.captures(&res_body.to_string()).unwrap().get(1).unwrap().as_str().to_string();
        let body = body.replace("\\","");
        let userinfo = serde_json::from_str::<userlist::Model>(&body).unwrap();
        userinfo.genre == 3
    }
    pub async fn is_login(&self,cookie: Cookie<'_>) -> bool {
        self.redis.select(0).await.unwrap();
        let res_body = self.redis.send(cmd("GET").arg(cookie.value().to_string()),None).await.unwrap();
        let re = Regex::new(r#"BulkString\("(.+)"\)"#).unwrap();
        let body = re.captures(&res_body.to_string()).unwrap().get(1).unwrap().as_str().to_string();
        let body = body.replace("\\","");
        let userinfo = serde_json::from_str::<userlist::Model>(&body).unwrap();
        userinfo.genre == 1||userinfo.genre == 2|| userinfo.genre == 3
    }
}

